

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

//SCE Chip Enable (active low) 	PD2
//RST Reset (active low)		PD3
//DC Data(high) / Command(low)  PD4
//DIN	MOSI Serial Data In 	PB3
//SCLK	Clock in 				PB5
//SS 							PB2


static const int ASCII[][5] =
{
	// First 32 characters (0x00-0x19) are ignored. These are
	// non-displayable, control characters.
	{0x00, 0x00, 0x00, 0x00, 0x00} // 20
	,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
	,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
	,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
	,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
	,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
	,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
	,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
	,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
	,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
	,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
	,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
	,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
	,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
	,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
	,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
	,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
	,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
	,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
	,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
	,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
	,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
	,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
	,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
	,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
	,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
	,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
	,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
	,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
	,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
	,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
	,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
	,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
	,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
	,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
	,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
	,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
	,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
	,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
	,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
	,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
	,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
	,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
	,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
	,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
	,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
	,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
	,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
	,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
	,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
	,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
	,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
	,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
	,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
	,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
	,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
	,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
	,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
	,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
	,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
	,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c \ -
	,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
	,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
	,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
	,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
	,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
	,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
	,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
	,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
	,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
	,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
	,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
	,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
	,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
	,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
	,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
	,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
	,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
	,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
	,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
	,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
	,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
	,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
	,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
	,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
	,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
	,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
	,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
	,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
	,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
	,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
	,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
	,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
	,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
	,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ©
	,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f ¨
};


void SPI_exe(int data){
	DDRB = (1 << 3) | (1 << 5) | (1 << 2);	// MOSI and SCK are output
	SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);	// enable SPI as master
	
	PORTB &= (1 << 2);				// initializing packet, pull SS low
	
	SPDR = data; 					// start data transmission
	while (!(SPSR & (1 << SPIF)));  // wait transfer finish
	
	PORTB |= (1 << 2);             // terminate packet, pull SS high
}


void lcd_writecmd(unsigned char cmd){
	PORTD &= ~(1<<4); // DC pin is low for commands
	PORTD &= ~(1<<2); // Chip enable (low)
	SPI_exe(cmd); // Transmit serial data
	PORTD |= (1<<2);  // Chip disable (high)
}

void lcd_writedata(unsigned char data){
	PORTD |= (1<<4);                         // DC pin is high for data
	PORTD &= ~(1<<2);                       // Chip enable (low)
	SPI_exe(data);                      // Transmit serial data
	PORTD |= (1<<2);                        // Chip disable (high)
}

void lcd_writechar(unsigned char character){
	for(int i=0; i<5; i++)                           // 5 char bytes per ASCII character
	lcd_writedata(ASCII[character - 0x20][i]);
	lcd_writedata(0x00);                             //  Add space after to make the letter 6 bytes long
}                                                   // 84 columns is divisible by 6, so letters are not

void lcd_print(unsigned char str){
	unsigned char i = 0;
	while (str[i]!=0)                       // while string entry is not 0 or NULL
	{
		lcd_writechar(str[i]);          // display char in string entry
		i++;                                // increment to next char
	}
}

void ClearLCD() {
	for(int i=0; i<504; i++)                 // 84 columns x 6 rows in bytes = 504 bytes to clear
	lcd_writedata(0x00);                     // clear LCD
}

void lcd_gotoxy(unsigned char x, unsigned char y) {
	lcd_writecmd(0x80 | x);                  // Column - 7th bit set to 1 OR'd with desired column #
	lcd_writecmd(0x40 | y);                  // Row - 6th bit set to 1 OR'd with desired row #
}

void lcd_setup() {
	DDRD |= (1<<2) | (1<<3) | (1<<4);    	// Set SCE, RST, DC to output
	DDRB |= (1<<3) | (1<<5);           // Set DIN and SCLK to output
	PORTD &= ~(1<<3);                       // Send low pulse to Reset display
	PORTD |= (1<<3);                        // Send high pulse to Reset display
	
	lcd_writecmd(0x21);                      // LCD extended commands
	lcd_writecmd(0xB8);                      // set LCD Vop (contrast)
	lcd_writecmd(0x04);                      // set temp coefficent
	lcd_writecmd(0x14);                      // LCD bias mode 1:40
	lcd_writecmd(0x20);                      // LCD basic commands
	lcd_writecmd(0x0C);                      // LCD normal video
}


void adc_setup(){
	//data will be L-Justified, PC0 for analog reading, 5V external voltage ref with 10uf cap
	ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);
	//make ADC enable and select ck/128
	ADCSRA = (1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
}


int main(void) {
	int temp = 0;   //Temperature
	DDRC = 0;       //Set PortC as input
	lcd_setup();	//Initialize LCD display
	adc_setup();	//Setup for ADC conversion
	
	while(1)
	{
		ADCSRA |= (1<<ADSC);			//Start Conversion
		while((ADCSRA&(1<<ADIF))==0);	//wait for end of conversion
	
		temp = ADCH;		//capture ADC

		lcd_gotoxy(1,1);              	// Set LCD cursor to the start of first line
		lcd_print(" Temperature = "); 	//Send data to the screen
		lcd_print(temp);
		lcd_print(" degrees F ");
		_delay_ms(500);					//delay to get new data
		ClearLCD();
	}
}